#pragma once
#include <iostream>
#include <mutex>
#include <chrono>
#include <iomanip>
#include <sstream>
#include <cstdarg>

class Logger {
public:
    enum Level {
        DEBUG,
        INFO,
        WARN,
        ERROR
    };

private:
    //static std::mutex logMutex;
    inline static std::mutex logMutex;

    static constexpr const char* RESET   = "\033[0m";
    static constexpr const char* RED     = "\033[31m";
    static constexpr const char* GREEN   = "\033[32m";
    static constexpr const char* YELLOW  = "\033[33m";
    static constexpr const char* CYAN    = "\033[36m";
    static constexpr const char* MAGENTA = "\033[35m";

    static const char* LevelColor(Level lv) {
        switch (lv) {
            case DEBUG: return CYAN;
            case INFO:  return GREEN;
            case WARN:  return YELLOW;
            case ERROR: return RED;
        }
        return RESET;
    }

    static const char* LevelName(Level lv) {
        switch (lv) {
            case DEBUG: return "DEBUG";
            case INFO:  return "INFO ";
            case WARN:  return "WARN ";
            case ERROR: return "ERROR";
        }
        return "UNK";
    }

    static std::string NowStr() {
        using namespace std::chrono;
        auto now = system_clock::now();
        auto t = system_clock::to_time_t(now);
        auto ms = duration_cast<milliseconds>(now.time_since_epoch()) % 1000;

        std::stringstream ss;
        ss << std::put_time(std::localtime(&t), "%Y-%m-%d %H:%M:%S");
        ss << "." << std::setw(3) << std::setfill('0') << ms.count();
        return ss.str();
    }

    // 格式化可变参数
    static std::string Format(const char* fmt, va_list args) {
        char buffer[1024];
        vsnprintf(buffer, sizeof(buffer), fmt, args);
        return buffer;
    }

public:

    // ========================= 核心日志输出 =========================
    static void Log(Level lv, const char* fmt, ...) {
        std::lock_guard<std::mutex> lock(logMutex);

        va_list args;
        va_start(args, fmt);
        std::string msg = Format(fmt, args);
        va_end(args);

        const char* color = LevelColor(lv);

        std::cout << color
                  << "[" << NowStr() << "] "
                  << "[" << LevelName(lv) << "] "
                  << msg
                  << RESET << std::endl;
    }

    // ========================= 便捷接口 =========================
    static void Debug(const char* fmt, ...) {
        va_list args;
        va_start(args, fmt);
        Log(DEBUG, fmt, args);
        va_end(args);
    }

    static void Info(const char* fmt, ...) {
        va_list args;
        va_start(args, fmt);
        Log(INFO, fmt, args);
        va_end(args);
    }

    static void Warn(const char* fmt, ...) {
        va_list args;
        va_start(args, fmt);
        Log(WARN, fmt, args);
        va_end(args);
    }

    static void Error(const char* fmt, ...) {
        va_list args;
        va_start(args, fmt);
        Log(ERROR, fmt, args);
        va_end(args);
    }
};
